package com.moss.cloud.auth.biz.service.impl;

import com.moss.cloud.auth.biz.exception.AuthErrorType;
import com.moss.cloud.auth.biz.model.dto.SmsDTO;
import com.moss.cloud.auth.biz.service.IAuthService;
import com.moss.cloud.common.core.constant.Constant;
import com.moss.cloud.common.core.constant.MsgTopic;
import com.moss.cloud.common.core.enums.MsgActionEnum;
import com.moss.cloud.common.core.enums.MsgTypeEnum;
import com.moss.cloud.common.core.model.dto.MessageDTO;
import com.moss.cloud.common.core.utils.BooleanHandel;
import com.moss.cloud.common.core.utils.GenUtil;
import com.moss.cloud.common.security.component.MessageEventSender;
import com.moss.cloud.common.security.component.RedisTemplateOps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Service
public class AuthServiceImpl implements IAuthService {
    private final RedisTemplateOps redisTemplateOps;
    private final ConsumerTokenServices consumerTokenServices;
    private final MessageEventSender messageEventSender;

    public AuthServiceImpl(RedisTemplateOps redisTemplateOps, ConsumerTokenServices consumerTokenServices,
                           MessageEventSender messageEventSender) {
        this.redisTemplateOps = redisTemplateOps;
        this.consumerTokenServices = consumerTokenServices;
        this.messageEventSender = messageEventSender;
    }

    @Override
    public Boolean getSmsCode(String mobile) {
        String code = GenUtil.randomCode();
        Boolean hasKey = redisTemplateOps.hasKey(Constant.SMS_CODE_KEY + mobile);
        BooleanHandel.isTureOrFalse(Boolean.TRUE.equals(hasKey)).trueOrFalseHandle(() -> {
            String phoneCode = (String) redisTemplateOps.get(Constant.SMS_CODE_KEY + mobile);
            BooleanHandel.trueThrow(StringUtils.isNotBlank(phoneCode)).throwMessage(AuthErrorType.CODE_FREQUENT);
            int sendNum = (int) redisTemplateOps.get(Constant.SMS_CODE_SEND_NUM + mobile);
            BooleanHandel.trueThrow(sendNum > 5).throwMessage(AuthErrorType.CODE_FREQUENT);
            this.setRedisTemplate(mobile, code);
        }, () -> {
            this.setRedisTemplate(mobile, code);
        });
        // 默认5分钟 以下发送短信验证码只适用moss-cloud-auth，有自己的短信业务请自行实现
        SmsDTO smsDTO = SmsDTO.builder().phoneNumbers(new String[]{"+86" + mobile})
                .sign("七心海棠")
                .templateID("358686")
                .templateParams(new String[]{code, "5"}).build();
        messageEventSender.sendMessage(MsgTopic.SMS_SEND_MESSAGE, new MessageDTO(
                MsgTypeEnum.ONE.name(), MsgActionEnum.ADD.name(), smsDTO));
        return Boolean.TRUE;
    }

    private void setRedisTemplate(String mobile, String code) {
        redisTemplateOps.set(Constant.SMS_CODE_KEY + mobile, code, 300);
        boolean hasKey = redisTemplateOps.hasKey(Constant.SMS_CODE_SEND_NUM + mobile);
        BooleanHandel.isTureOrFalse(hasKey).trueOrFalseHandle(() -> {
            redisTemplateOps.incr(Constant.SMS_CODE_SEND_NUM + mobile, 1);
        }, () -> {
            redisTemplateOps.expire(Constant.SMS_CODE_SEND_NUM + mobile, 1800);
        });
    }

    /**
     * 退出登录
     *
     * @param request
     */
    @Override
    public Boolean logout(HttpServletRequest request) {
        String authHeader = request.getHeader("Authorization");
        BooleanHandel.trueThrow(StringUtils.isBlank(authHeader)).throwMessage(AuthErrorType.ACCESS_DENIED);
        if (StringUtils.isNotBlank(authHeader)) {
            String tokenValue = authHeader.replace("Bearer", "").trim();
            consumerTokenServices.revokeToken(tokenValue);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
